package com.calm.editor.servlet;

import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Method;

import org.springframework.context.ApplicationContext;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import com.google.gson.stream.JsonReader;

public class HandlerExecuter implements Runnable {
	private String reader;
	private ApplicationContext context;
	private HelloMessageInbound messageInbound;
	private Gson gson = new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() {
		
		@Override
		public boolean shouldSkipField(FieldAttributes f) {
			Expose annotation = f.getAnnotation(Expose.class);
			if(annotation==null){
				return false;
			}
			return !annotation.serialize();
		}
		
		@Override
		public boolean shouldSkipClass(Class<?> clazz) {
			return false;
		}
	}).create();
	public HandlerExecuter(String reader, ApplicationContext context,HelloMessageInbound messageInbound) {
		super();
		this.reader = reader;
		this.context = context;
		this.messageInbound= messageInbound;
	}

	@Override
	public void run() {
		JsonReader aa = new JsonReader(new StringReader(reader));
		aa.setLenient(true);
		Parameter para = gson.fromJson(aa, Parameter.class);
		Result<?> result=new Result<>();
		try {
			Object bean = context.getBean(para.getBean());
			Class<?> clazz = bean.getClass();
			Method[] methods = clazz.getMethods();
			for(Method m:methods){
				if(m.getName().equals(para.getMethod())){
					Class<?>[] parameterTypes = m.getParameterTypes();
					int length=parameterTypes.length;
					Object[] args=new Object[length];
					for(int i=0;i<length;i++){
						Class<?> type = parameterTypes[i];
						if(type.equals(Result.class)){
							args[i]=result;
						}else{
							Object fromJson = gson.fromJson(para.getData(), parameterTypes[0]);
							args[i]=fromJson;
						}
					}
					m.invoke(bean, args);
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setMessage(e.getMessage());
			result.setStatus(Result.STATUS_ERROR);
		}
		String json = gson.toJson(result);
		try {
			messageInbound.send(json);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}
